package com.youlu.campus.service.invite.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.tencentcloudapi.gse.v20191112.models.UpdateAliasRequest;
import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.UserInviteRequest;
import com.youlu.campus.entity.VO.req.UserInviteCreateVO;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.base.BaseService;
import com.youlu.campus.service.integral.UserIntegralService;
import com.youlu.campus.service.visitor.VisitorUserService;
import com.youlu.campus.service.invite.UserInviteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author zhuhuaiqi
 * @date 2020/11/13 17:58
 */
@Slf4j
@Service
public class UserInviteServiceImpl extends BaseService implements UserInviteService {


    @Autowired
    private UserIntegralService userIntegralService;
    @Autowired
    private VisitorUserService userService;
    @Autowired
    private ActivityService activityService;

    @Override
    public boolean createInvite(UserInviteRequest request) {
        log.info(":>>> ---->>>>开始创建邀请<<<<----:{}", JSON.toJSONString(request));
        if (Objects.isNull(request) || StringUtils.isBlank(request.getSharedByOpenId())
                || StringUtils.isBlank(request.getBizType()) || StringUtils.isBlank(request.getBizId())) {
            log.error(":>>> 创建邀请错误:参数错误");
        }
        UserPO user = request.getUserPO();
        // 邀请人信息
        UserPO invitedUser = userService.getUserByOpenId(request.getSharedByOpenId());
        if (invitedUser == null) {
            log.info(":>>> 被邀请人不存在:{}", request.getSharedByOpenId());
            return false;
        }
        log.info("createInvite userId {} openId {}", user.getId(), request.getSharedByOpenId());
        if (super.resubmit(2L, "createInvite", user.getId(), request.getOpenId())) {
            log.error(":>>> 用户邀请加锁失败");
            return false;
        }
        //邀请业务类型:activity(活动)、attendance(打卡)、job(工作)
        switch (request.getBizType()) {
            case "activity": {
                log.info(":>>> 邀请的是活动:{}", request.getBizId());
                ActivityInfo activityInfo = this.findOne(request.getBizId());
                if (Objects.isNull(activityInfo)) {
                    log.error(":>>> 活动信息为空:{}", request.getBizId());
                    return false;
                }
                UserInviteCreateVO req = new UserInviteCreateVO();
                req.setQa(activityInfo.getHasQa());
                req.setActivityId(activityInfo.getId());
                req.setInvitedByUserInfo(invitedUser);
                req.setTargetOpenId(user.getOpenId());
                req.setInviteTime(new Date());
                req.setTaskBizType(TaskBizType.INVITE);
                req.setTargetUser(user);
                req.setAppId(request.getAppId());
                req.setPlatform(request.getPlatform());
                ActivityTaskInfo taskInfo = activityService.findActivityTaskInfo(activityInfo.getId(), TaskBizType.INVITE);
                if (Objects.nonNull(taskInfo)) {
                    req.setTaskId(taskInfo.getId());
                }
                activityService.createActivityInvite(req);
                break;
            }
            case "attendance": {
                log.info(":>>> 邀请的是打卡:{}", request.getBizId());
                ActivityInfo activityInfo = this.findOne(request.getBizId());
                if (Objects.isNull(activityInfo)) {
                    log.error(":>>> 打卡信息为空:{}", request.getBizId());
                    return false;
                }
                UserInviteCreateVO req = new UserInviteCreateVO();
                req.setQa(activityInfo.getHasQa());
                req.setActivityId(activityInfo.getId());
                req.setInvitedByUserInfo(invitedUser);
                req.setTargetOpenId(user.getOpenId());
                req.setTargetUser(user);
                req.setInviteTime(new Date());
                req.setTaskBizType(TaskBizType.INVITE);
                if (StringUtils.isNotBlank(request.getDayTime())) {
                    Date dateTime = TimeUtils.parse(request.getDayTime(), "yyyy-MM-dd");
                    req.setDayTime(dateTime);
                }
                activityService.createActivityInvite(req);
                break;
            }
            case "job": {
                log.info(":>>> 邀请的是工作:{}", request.getBizId());
                break;
            }
            default:
                break;
        }
        return true;
    }

    @Override
    public Long getInvitedNum(String userId, String activityId) {
        Query query = new Query().addCriteria(Criteria.where("invitedByUserId").is(userId).and("activityId").is(activityId).and("joinStatus").is(Boolean.TRUE));
        return mongoTemplate.count(query, UserInviteRecord.class);
    }

    @Override
    public Long getInvitedNumNew(String userId, String activityId) {
        Long cu = System.currentTimeMillis();
        log.info(":>>> 开始获取用户:{} 活动:{} 邀请数量", userId, activityId);
        Query query = new Query().addCriteria(Criteria.where("invitedByUserId").is(userId).and("activityId").is(activityId).and("joinStatus").is(Boolean.TRUE));
        query.withHint("{ 'activityId_1_invitedByUserId_1_joinStatus_1' : 1 }");
        Long c = mongoTemplate.count(query, mongoTemplate.getCollectionName(UserInviteRecord.class));
        log.info(":>>> 结束获取用户:{} 活动:{} 邀请数量耗时:{} 毫秒", userId, activityId, (System.currentTimeMillis() - cu));
        return c;
    }

    @Override
    public void updateInvitedNum(String activityId) {
        log.info(":>>> 开始更新活动邀请人数:{}", activityId);
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(activityId).and("joined").is(Boolean.TRUE));
        Long count = mongoTemplate.count(query, UserParticipateActivityInfo.class);
        log.info(":>>> 开始更新活动邀请人数:{},{}", activityId, count);
        if (count <= 0) {
            return;
        }
        Date date = new Date();
        Integer pages = count.intValue() / 1000 + 1;
        for (int i = 1; i <= pages; i++) {
            PageRequest pageRequest = PageRequest.of(i - 1, 1000);
            Sort sort = Sort.by(Sort.Direction.DESC, "invitedNum");
            query.with(sort);
            List<UserParticipateActivityInfo> ups = mongoTemplate.find(query.with(pageRequest), UserParticipateActivityInfo.class);
            if (CollectionUtils.isEmpty(ups)) {
                continue;
            }
            for (UserParticipateActivityInfo u : ups) {
                if (StringUtils.isBlank(u.getUserId())) {
                    continue;
                }
                Long invitedNum = this.getInvitedNum(u.getUserId(), activityId);
                this.updateInvitedNum(u.getId(), invitedNum, date);
            }
        }
    }


    private ActivityInfo findOne(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityInfo activityInfo = mongoTemplate.findOne(query, ActivityInfo.class);
        return activityInfo;
    }

    private void updateInvitedNum(String id, Long invitedNum, Date updateTime) {
        Query q = new Query();
        q.addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("invitedNum", invitedNum.intValue());
        update.set("updatedTime", updateTime);
        UpdateResult result = mongoTemplate.updateFirst(q, update, UserParticipateActivityInfo.class);
        log.info(":>>> 更新用户邀请人数量结果:{},{},{}", id, invitedNum, result.getModifiedCount() > 0 ? true : false);
    }


}
